package project;
import static project.GUIComponents.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.text.ParseException;

import javax.media.jai.JAI;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import static project.Pixila.*;
import com.sun.media.jai.widget.DisplayJAI;
import static project.PixieFactory.*;
import static project.PixieConstants.*;

@SuppressWarnings("serial")
public class PixieClasses{
	static class IconButton extends JButton{
		public IconButton(String iconPath, String tipText){
			this.setFont(new Font("Garamond", 0, 12));
			this.setToolTipText(tipText);
			this.setFocusable(false);
			//this.setBorderPainted(false);
			this.setIcon(retrieveIcon(iconPath));
			this.setPreferredSize(new Dimension(45,45));
		}

	}

	static class ImageContainer extends DisplayJAI{
		private static ImageContainer oneImageHolder = null;
		private String position="";
		
		private ImageContainer(){
			this.addMouseMotionListener(this);
			this.addMouseListener(this);
		} 
		public void mouseMoved(MouseEvent e) {
			position =  "[" + e.getX() + ", " + e.getY() + "]";
			mousePositionTracker.setText(position);
		}
		public void mouseExited(MouseEvent e) {
			mousePositionTracker.setText("");
			bottomPanelMessage.setText("");
		}

		public void set(RenderedImage im){
			super.set(im);
		}
		
		public static ImageContainer getImageHolder(){
			if(oneImageHolder == null)
				oneImageHolder = new ImageContainer();
			return oneImageHolder;
		}
	}

	static class SaveAsItem extends JMenuItem{
		public SaveAsItem(final String formatType){
			setFont(new Font("Garamond", 2, 15));
			this.setPreferredSize(new Dimension(70, 30));
			this.setText(formatType);
			this.setIcon(retrieveIcon(imageSaveIconPath));
			this.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					try{
						saveAsFormat(currentImage,formatType);
					}catch(IllegalArgumentException e){}
				}
			});
		}
	}

	static class toneItem extends JPanel implements MouseInputListener{
		double[][] colorMatrix;
		JLabel label;
		public toneItem(String text, Color fgColor, double[][] rgb){
			colorMatrix = rgb;
			this.setBackground(fgColor);
			this.setToolTipText(text);
			label = new JLabel(text);
			this.add(label);
			label.setVisible(false);
			label.setForeground(reverse(fgColor));
			label.setFont(new Font("Default", Font.BOLD, 10));
			this.setPreferredSize(new Dimension(100, 20));
			this.addMouseListener(this);
		} 

		public RenderedImage applyColorTone(RenderedImage src){
			ParameterBlock toneParameters = new ParameterBlock();
			toneParameters.addSource(src);
			toneParameters.add(colorMatrix);
			try{
				return JAI.create("bandcombine", toneParameters);
			}catch(IllegalArgumentException e){
				return src;
			}
		}

		private Color reverse(Color c) {
			return new Color(255-c.getRed(), 255-c.getGreen(), 255-c.getBlue());
		}


		public void mouseClicked(MouseEvent e) {
			colorMenu.setVisible(false);
			addToUndoStack();
			currentImage = applyColorTone(currentImage);
			updateDisplay();
			label.setVisible(false);
		}

		public void mouseEntered(MouseEvent e) {
			RenderedImage temp = null;
			temp = applyColorTone(currentImage);
			fitToScreen(temp);
			label.setVisible(true);
		}

		public void mouseExited(MouseEvent e) {
			updateDisplay();
			label.setVisible(false);
		}

		public void mousePressed(MouseEvent e) {}

		public void mouseReleased(MouseEvent e) {}
		public void mouseDragged(MouseEvent e) {}
		public void mouseMoved(MouseEvent e) {}
	}

	static class DisplayToggle extends JButton implements ActionListener{
		enum DisplayMode{FULL, FIT};
		DisplayMode state;

		public DisplayToggle(){
			this.setFont(new Font("Garamond", 1, 12));
			this.setPreferredSize(new Dimension(60,60));
			this.setFocusable(false);
			this.addActionListener(this);
		}

		public void changeState(){
			if(state == DisplayMode.FULL)
				this.setFit();
			else if(state == DisplayMode.FIT)
				this.setFull();
		}

		public void setFit(){
			state = DisplayMode.FIT;
			this.setToolTipText("Fit To Screen");
			this.setIcon(retrieveIcon(fitIconPath));
		}

		public void setFull(){
			state = DisplayMode.FULL;
			this.setToolTipText("Display Full Size");
			this.setIcon(retrieveIcon(fullIconPath));
		}

		public void actionPerformed(ActionEvent e){
			if(state==DisplayMode.FIT)
				updateDisplay();
			else if(state==DisplayMode.FULL)
				showFullSize();
			this.changeState();
		}

	}

	enum InputType{WIDTH, HEIGHT, SCALE};

	static class ResizeSpinner extends JSpinner implements ChangeListener{
		private InputType type;
		SpinnerModel model = new SpinnerNumberModel(100, 0, 3000, 1);
		SmartResizeBox editor;

		public ResizeSpinner(InputType type){ 
			super();
			this.type = type;
			this.setModel(model);
			editor = new SmartResizeBox(this);
			this.setEditor(editor);
			editor.setText(this.getValue().toString());
			
			//this.setPreferredSize(new Dimension(50,30));
			this.addChangeListener(this);
		}
		
		public ResizeSpinner(InputType type, SpinnerModel sm){
			this(type);
			this.setModel(sm);
		}

		public void stateChanged(ChangeEvent e) {
			
			try {
				editor.setText(this.getValue().toString());
				commitEdit();
			} catch (ParseException ex) {System.out.println("Error committing changes");}
			 catch (IllegalStateException x) {/*System.out.println("Multiple changes at a time.");*/}


/*			int t = (Integer) ((SpinnerNumberModel) this.getModel()).getMaximum();
			if(Integer.parseInt(editor.getText()) == t) {
				editor.setText(String.valueOf(t));
				//JOptionPane.showMessageDialog(null, "Max: "+ t);
			}
*/			

		} 

		public int getNumValue(){
			return Integer.parseInt(editor.getText());
		}

		public InputType getType(){
			return type;
		}
	}

	static class SmartResizeBox extends JTextField implements DocumentListener{
		private ResizeSpinner owner=null;

		public SmartResizeBox(ResizeSpinner comp){ 
			this.owner = comp;
			this.getDocument().addDocumentListener(this);
			this.setBackground(new Color(230,240,255));
			//this.setForeground(Color.WHITE);
			this.setFont(new Font("Garamond", Font.BOLD, 14));
			this.setHorizontalAlignment(JTextField.RIGHT);
		}

		public void changedUpdate(DocumentEvent e){	doMonitor();}
		public void insertUpdate(DocumentEvent e){	doMonitor();} 
		public void removeUpdate(DocumentEvent e){	doMonitor();}

		public void doMonitor(){
				try{
					owner.setValue(Integer.parseInt(getText()));
				}catch(Exception ex){}

				if(this.isFocusOwner() && ratioCheck.isSelected())
				{
					if(owner.getType()==InputType.WIDTH)
						widthMonitor();
					else if(owner.getType()==InputType.HEIGHT)
						heightMonitor();
					else if(owner.getType()==InputType.SCALE)
						scaleMonitor();
					
				}

				try{
					this.setText(String.valueOf(owner.getValue()));
				}catch(Exception ex){}


		}
	}

	static class DropButton extends JButton implements ActionListener{
		private JPopupMenu popMenu=null;
		private JPanel face;
		private String title=null;
		
		public DropButton(String iconPath, String tipText){
			super();
			this.setToolTipText(tipText);
			title = tipText;
			this.setFocusable(false);
			//this.setPreferredSize(new Dimension(140,45));
			this.addActionListener(this);
			
			//setText("<html>"+tipText+"&darr;&darr;<html>");
			//setFont(new Font("Comic Sans MS", 0, 16));
			//setIcon(retrieveIcon(iconPath));
			
			prepareImage(iconPath, tipText);
			//this.add(face);
			//this.add(new JLabel("Hi"));
			//this.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 5));
			//JButton jb;
			//this.add(new JLabel("Hi"));
		}

		private void prepareImage(String imgpath, String text) {
			JLabel name = new JLabel(text);
			name.setFont(new Font("Garamond", Font.BOLD, 16));
			JLabel icon = new JLabel(retrieveIcon(imgpath));
			JLabel arrow = new JLabel(retrieveIcon(arrowDownIconPath));
			face = new JPanel();
			this.setBorder(null);
			addComponents(this, new FlowLayout(FlowLayout.RIGHT, 4,5), icon, name , separator(40) , arrow);// new GridBagLayout()
			//this.add(face);
		}

		public void actionPerformed(ActionEvent e){
			popMenu.show(this, 0, this.getHeight());
		}
		
		public void setPopUpMenu(JPopupMenu popMenu){
			this.popMenu = popMenu;	
			//this.popMenu.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.gray, new Color(200,200,200)));
			//this.popMenu.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray, 2), title));
			this.popMenu.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED,Color.white,Color.black), title));
			//this.popMenu.setBackground(new Color(2,25,90));
		}
	}

}
